package com.ruoyi.system.service.impl;

import java.text.SimpleDateFormat;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.util.*;
import java.util.function.Function;
import java.util.stream.Collectors;

import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.date.DateTime;
import cn.hutool.core.util.IdUtil;
import cn.hutool.core.util.StrUtil;
import com.ruoyi.common.annotation.DataScope;
import com.ruoyi.common.core.domain.AjaxResult;
import com.ruoyi.common.core.domain.entity.SysDept;
import com.ruoyi.common.core.domain.entity.SysUser;
import com.ruoyi.common.utils.DateUtils;
import com.ruoyi.common.utils.PushMsgUtils;
import com.ruoyi.common.utils.SecurityUtils;
import com.ruoyi.common.utils.StringUtils;
import com.ruoyi.system.domain.IdDto;
import com.ruoyi.system.domain.PushMsgDto;
import com.ruoyi.system.domain.SysPushFileRecord;
import com.ruoyi.system.mapper.SysDeptMapper;
import com.ruoyi.system.mapper.SysPushFileRecordMapper;
import com.ruoyi.system.mapper.SysUserMapper;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import com.ruoyi.system.mapper.SysPushRecordMapper;
import com.ruoyi.system.domain.SysPushRecord;
import com.ruoyi.system.service.ISysPushRecordService;

/**
 * 消息推送Service业务层处理
 *
 * @author ruoyi
 * @date 2025-08-31
 */
@Service
public class SysPushRecordServiceImpl implements ISysPushRecordService {
    @Autowired
    private SysPushRecordMapper sysPushRecordMapper;

    @Autowired
    private SysUserMapper sysUserMapper;

    @Autowired
    private PushMsgUtils pushMsgUtils;

    @Autowired
    private SysPushFileRecordMapper sysPushFileRecordMapper;

    @Autowired
    private SysDeptMapper sysDeptMapper;

    /**
     * 查询消息推送
     *
     * @param id 消息推送主键
     * @return 消息推送
     */
    @Override
    public SysPushRecord selectSysPushRecordById(Long id) {
        return sysPushRecordMapper.selectSysPushRecordById(id);
    }

    /**
     * 查询消息推送列表
     *
     * @param sysPushRecord 消息推送
     * @return 消息推送
     */
    @Override
    @DataScope(deptAlias = "d", userAlias = "u")
    public List<Map<String, Object>> selectSysPushRecords(SysPushRecord sysPushRecord) {

        List<Map<String, Object>> result = new ArrayList<>();

        List<SysPushRecord> sysPushRecords = sysPushRecordMapper.selectSysPushRecordList(sysPushRecord);

        Map<String, List<SysPushRecord>> batchPushRecordList = sysPushRecords.stream().collect(Collectors.groupingBy(SysPushRecord::getBatchNo));


        batchPushRecordList.entrySet().forEach(b -> {

            Map<String, Object> map = new HashMap<>();
            map.put("batchNo", b.getKey().toUpperCase());

            List<SysPushRecord> valueList = b.getValue();

            SysPushRecord record = valueList.get(0);
            map.put("pushTime", record.getPushTime());
            map.put("title", record.getTitle());
            map.put("msg", record.getMsg());
            map.put("id", record.getId());
            map.put("label", record.getNoticeLabel());
            map.put("category", record.getCategory());


            List<Long> receiverUserIdList = sysPushRecordMapper.selectReceiveUserList(b.getKey());

            List<SysUser> sysUsers = sysUserMapper.selectListNoticeStatus(receiverUserIdList, record.getBatchNo());

            String receiveUsers = sysUsers.stream().map(SysUser::getNickName).collect(Collectors.joining(";"));
            map.put("receiveUsers", receiveUsers);

            if (CollUtil.isNotEmpty(sysUsers)) {

                map.put("receiveUserList", sysUsers);
            }

            result.add(map);

        });

        result.sort((map1, map2) -> {
            Date time1 = (Date) map1.get("pushTime");
            Date time2 = (Date) map2.get("pushTime");
            // 注意：如果pushTime可能为null，需要添加null值处理逻辑
            if (time1 == null && time2 == null) return 0;
            if (time1 == null) return 1; // 把null值放在后面
            if (time2 == null) return -1;
            return time2.compareTo(time1); // 降序排列
        });

        return result;
    }

    @Override
    @DataScope(deptAlias = "d", userAlias = "u")
    public List<SysPushRecord> selectSysPushRecordList(SysPushRecord sysPushRecord) {
        return sysPushRecordMapper.selectSysPushRecordList(sysPushRecord);
    }

    /**
     * 新增消息推送
     *
     * @param sysPushRecord 消息推送
     * @return 结果
     */
    @Override
    public int insertSysPushRecord(SysPushRecord sysPushRecord) {
        sysPushRecord.setCreateTime(DateUtils.getNowDate());
        return sysPushRecordMapper.insertSysPushRecord(sysPushRecord);
    }

    /**
     * 修改消息推送
     *
     * @param sysPushRecord 消息推送
     * @return 结果
     */
    @Override
    public int updateSysPushRecord(SysPushRecord sysPushRecord) {
        sysPushRecord.setUpdateTime(DateUtils.getNowDate());
        return sysPushRecordMapper.updateSysPushRecord(sysPushRecord);
    }

    /**
     * 批量删除消息推送
     *
     * @param ids 需要删除的消息推送主键
     * @return 结果
     */
    @Override
    public AjaxResult deleteSysPushRecordByIds(String[] ids) {

        sysPushRecordMapper.deleteSysPushRecordByIds(ids);

        return AjaxResult.success();

    }

    /**
     * 删除消息推送信息
     *
     * @param id 消息推送主键
     * @return 结果
     */
    @Override
    public int deleteSysPushRecordById(Long id) {
        return sysPushRecordMapper.deleteSysPushRecordById(id);
    }


    @Override
    public AjaxResult pushMessage(PushMsgDto dto) {


        if (CollUtil.isEmpty(dto.getUserIdList())) {
            return AjaxResult.error("请勾选推送用户!");
        }


        List<SysUser> sysUsers = sysUserMapper.selectUserList(null);

        Map<Long, SysUser> allUserMap = sysUsers.stream().collect(Collectors.toMap(SysUser::getUserId, Function.identity()));

        String batchNo = IdUtil.fastSimpleUUID();


        List<SysPushRecord> pushRecordList = new ArrayList<>();
        List<SysPushFileRecord> pushRecordFileList = new ArrayList<>();
        for (Long userId : dto.getUserIdList()) {


            SysUser sysUser = allUserMap.get(userId);

            if (sysUser != null) {
                if (StrUtil.isNotBlank(sysUser.getCid())) {
                    String type = PushMsgUtils.OFFLINE_PUSH;
                    pushMsgUtils.pushToSingleByCid(sysUser.getCid(), dto.getTitle(), dto.getMsg(), type);
                }
            }

            SysPushRecord sysPushRecord = new SysPushRecord();
            long snowflakeNextId = IdUtil.getSnowflakeNextId();

            sysPushRecord.setId(snowflakeNextId);
            sysPushRecord.setPushTime(DateTime.now());
            sysPushRecord.setPushUserId(SecurityUtils.getUserId());
            sysPushRecord.setTitle(dto.getTitle());
            sysPushRecord.setMsg(dto.getMsg());
            sysPushRecord.setReceiverUserId(userId);
            sysPushRecord.setBatchNo(batchNo);
            sysPushRecord.setNoticeLabel(dto.getNoticeLabel());
            sysPushRecord.setCategory(dto.getCategory());
            sysPushRecord.setStatus(0);

//            sysPushRecordMapper.insertSysPushRecord(sysPushRecord);

            pushRecordList.add(sysPushRecord);

            if (CollUtil.isNotEmpty(dto.getFileUrls())) {

                for (SysPushFileRecord file : dto.getFileUrls()) {

                    SysPushFileRecord filePo = new SysPushFileRecord();
                    filePo.setId(IdUtil.getSnowflakeNextId());
                    filePo.setFileName(file.getFileName());
                    filePo.setFileUrl(file.getFileUrl());
                    filePo.setPushRecordId(snowflakeNextId);

                    pushRecordFileList.add(filePo);
                }
            }
        }


        if (CollUtil.isNotEmpty(pushRecordList)) {
            sysPushRecordMapper.batchInsertSysPushRecord(pushRecordList);
        }

        if (CollUtil.isNotEmpty(pushRecordFileList)) {
            sysPushFileRecordMapper.batchInsertSysPushFileRecord(pushRecordFileList);
        }


        return AjaxResult.success();
    }


    @Override
    public AjaxResult noticeList() {


        List<Map<String, Object>> result = new ArrayList<>();

        List<SysPushRecord> sysPushRecords = sysPushRecordMapper.selectSysPushRecordList(null);

        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");

        for (SysPushRecord sysPushRecord : sysPushRecords) {

            Map<String, Object> map = new HashMap<>();
            map.put("title", sysPushRecord.getTitle());
            map.put("releaseTime", sdf.format(sysPushRecord.getPushTime()));
            map.put("id", sysPushRecord.getId());


            result.add(map);
        }

        return AjaxResult.success(result);
    }


    @Override
    public AjaxResult noticeDetail(IdDto dto) {
        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");

        Map<String, Object> result = new HashMap<>();

        SysPushRecord sysPushRecord = sysPushRecordMapper.selectSysPushRecordById(dto.getId());

        result.put("id", String.valueOf(sysPushRecord.getId()));
        result.put("title", sysPushRecord.getTitle());
        result.put("content", sysPushRecord.getMsg());
        result.put("releaseTime", sdf.format(sysPushRecord.getPushTime()));
        result.put("status", sysPushRecord.getStatus());
        result.put("label", sysPushRecord.getNoticeLabel());
        result.put("category", sysPushRecord.getCategory());


        SysPushFileRecord sysPushFileRecord = new SysPushFileRecord();
        sysPushFileRecord.setPushRecordId(dto.getId());
        List<SysPushFileRecord> firlList = sysPushFileRecordMapper.selectSysPushFileRecordList(sysPushFileRecord);

        if (CollUtil.isNotEmpty(firlList)) {
            result.put("fileUrlList", firlList);
        } else {
            result.put("fileUrlList", new ArrayList<>());
        }

        return AjaxResult.success(result);

    }


    @Override
    public List<SysPushRecord> noticeAppList(SysPushRecord sysPushRecord) {

        Long userId = SecurityUtils.getUserId();

        sysPushRecord.setReceiverUserId(Long.valueOf(userId));

        List<SysPushRecord> sysPushRecords = sysPushRecordMapper.selectAppSysPushRecordList(sysPushRecord);


        return sysPushRecords;
    }

    @Override
    public AjaxResult test(PushMsgDto dto) {


        List<SysUser> sysUsers = sysUserMapper.selectList(dto.getUserIdList());

        SysUser sysUser = sysUsers.get(0);

        String type = PushMsgUtils.OFFLINE_PUSH;
        pushMsgUtils.pushToSingleByCid(sysUser.getCid(), dto.getTitle(), dto.getMsg(), type);
        return AjaxResult.success();
    }

    @Override
    public AjaxResult view(String batchNo) {

        Map<String, Object> result = new HashMap<>();

        SysPushRecord queryPushRecord = new SysPushRecord();
        queryPushRecord.setBatchNo(batchNo);
        List<SysPushRecord> sysPushRecords = sysPushRecordMapper.selectSysPushRecordList(queryPushRecord);

        if (CollUtil.isEmpty(sysPushRecords)) {
            return AjaxResult.error("该通知不存在!");
        }

        SysPushRecord sysPushRecord = sysPushRecords.get(0);


        result.put("title", sysPushRecord.getTitle());
        result.put("msg", sysPushRecord.getMsg());
        result.put("label", sysPushRecord.getNoticeLabel());
        result.put("category", sysPushRecord.getCategory());

        List<SysDept> sysDepts = sysDeptMapper.selectDeptList(null);


        List<Long> userIdList = sysPushRecords.stream().map(SysPushRecord::getReceiverUserId).distinct().collect(Collectors.toList());
        if (CollUtil.isNotEmpty(userIdList)) {

            List<SysUser> sysUsers = sysUserMapper.selectList(userIdList);

            List<Long> deptIdList = sysUsers.stream().filter(u -> u.getDeptId() != null).map(SysUser::getDeptId).collect(Collectors.toList());


            List<SysDept> sysDeptList = sysDeptMapper.listDeptIdList(deptIdList);

            Map<Long, List<SysDept>> deptMap = sysDeptList.stream().filter(d -> d.getDeptId() != null).collect(Collectors.groupingBy(SysDept::getDeptId));

            StringBuilder stringBuilder = new StringBuilder("");

            for (Map.Entry<Long, List<SysDept>> obj : deptMap.entrySet()) {


                List<SysUser> userList
                        = sysUsers.stream().filter(u -> obj.getKey().equals(u.getDeptId())).collect(Collectors.toList());

                if (CollUtil.isEmpty(userList)) {
                    continue;
                }

                SysDept sysDept = obj.getValue().get(0);
                stringBuilder.append(sysDept.getDeptName());
                stringBuilder.append("<br>");
                stringBuilder.append(userList.stream().map(SysUser::getNickName).collect(Collectors.joining(";")));
                stringBuilder.append("<br>");

            }


            result.put("userList", stringBuilder.toString());
        } else {
            result.put("userList", new ArrayList<>());
        }


        SysPushFileRecord queryPushFileRecord = new SysPushFileRecord();
        queryPushFileRecord.setPushRecordId(sysPushRecord.getId());
        List<SysPushFileRecord> sysPushFileRecords = sysPushFileRecordMapper.selectSysPushFileRecordList(queryPushFileRecord);

        Map<String, List<SysPushFileRecord>> pushFileRecordMap = sysPushFileRecords.stream().collect(Collectors.groupingBy(SysPushFileRecord::getFileUrl));

        List<Map<String, Object>> fileList = new ArrayList<>();
        pushFileRecordMap.entrySet().forEach(obj -> {

            SysPushFileRecord sysPushFileRecord = obj.getValue().get(0);

            Map<String, Object> map = new HashMap<>();
            map.put("fileName", sysPushFileRecord.getFileName());
            map.put("fileUrl", sysPushFileRecord.getFileUrl());
            fileList.add(map);
        });
        result.put("fileList", fileList);

        return AjaxResult.success(result);
    }
}
